Skip to content

feat: weighted Reciprocal Rank Fusion for recall#1631

Open
dcbouius wants to merge 3 commits into
mainfrom
feat/weighted-rrf
Open

feat: weighted Reciprocal Rank Fusion for recall#1631
dcbouius wants to merge 3 commits into
mainfrom
feat/weighted-rrf

Conversation

@dcbouius
Copy link
Copy Markdown
Contributor

Summary

  • Adds per-strategy weights to RRF fusion, allowing tuning of how much each retrieval method (semantic, BM25, graph, temporal) influences the merged ranking
  • Weights follow the hierarchical config model: server env vars → per-bank config → per-request override
  • Default weights are all 1.0, preserving existing behavior exactly

API

New optional retrieval_weights field on the recall request:

{
  "query": "What happened at the meeting?",
  "retrieval_weights": {
    "semantic": 1.0,
    "bm25": 1.0,
    "graph": 2.0,
    "temporal": 1.0
  }
}

Keys: semantic, bm25, graph, temporal. Values are multipliers (1.0 = default, 2.0 = double influence, 0.0 = disabled). Omitted keys default to bank/server config.

Configuration

Server-level defaults via env vars:

  • HINDSIGHT_API_RECALL_WEIGHT_SEMANTIC (default: 1.0)
  • HINDSIGHT_API_RECALL_WEIGHT_BM25 (default: 1.0)
  • HINDSIGHT_API_RECALL_WEIGHT_GRAPH (default: 1.0)
  • HINDSIGHT_API_RECALL_WEIGHT_TEMPORAL (default: 1.0)

All four are in _CONFIGURABLE_FIELDS, so they can be overridden per-bank via the config API.

Changes

  • fusion.pyreciprocal_rank_fusion() accepts optional weights dict; formula becomes w_i / (k + rank)
  • config.py — 4 new hierarchical config fields with env var + default support
  • http.pyRecallRequest.retrieval_weights field
  • memory_engine.py — Merges config + request weights, passes to RRF
  • interface.pyretrieval_weights param on abstract recall_async
  • Control plane proxy + client types updated

Test plan

  • 10 unit tests covering: unweighted default, None/1.0 equivalence, high weight boosting, zero weight disabling, partial weights, temporal support, ranking reversal, source rank preservation
  • CI passes

Add per-strategy weights to RRF fusion, allowing tuning of how much
each retrieval method (semantic, BM25, graph, temporal) influences
the merged ranking.

Weights follow the hierarchical config model: server defaults via env
vars (HINDSIGHT_API_RECALL_WEIGHT_*), overridable per-bank via config
API, and per-request via the retrieval_weights field on recall.

Default weights are all 1.0, preserving existing behavior exactly.
@cdbartholomew
Copy link
Copy Markdown
Contributor

@dcbouius I am not sure this is the best solution to making graph results higher weight. We already have "boosters" for things like recency that work after the rerank. We can just add a graph boost. Its is simpler and guaranteed to move up the graph results. Doing it during the fusion increases the chances that the graph results will win, but the rerank could still decided otherwise.

dcbouius added 2 commits May 14, 2026 11:47
… recall_async

The weight resolution logic referenced budget_config_dict which only
exists in recall_async scope, not in _search_with_retries. Move the
resolution to recall_async and pass the computed rrf_weights through.
Add retrieval_weights field to generated Go, Python, and TypeScript
clients to match the new recall API parameter.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants